#!/usr/bin/env python
# -*- coding:utf-8 -*-
'''
@File    :   excel_utils.py
@Time    :   2024/12/04 20:53:51
@Author  :   xiangyu Chen
@Version :   1.0
@Contact :   yu112yu@sina.com
@License :   (C)Copyright 2017-2018, Liugroup-NLPR-CASIA
@Desc    :   None
'''

import openpyxl
from openpyxl.worksheet.worksheet import Worksheet
import os
from win32com.client import DispatchEx
from utils.basic_utils import get_file_path


class MyPyExcel:
    '''
    Python操作Excel(.xlsx)
    '''
    def __init__(self, file_name, data_only=True):
        '''
        初始化功能，加载文件
        strOpenFilePath，要打开的excel文件路径
        '''
        # self.strOpenFilePath = get_file_path(file_name)  #文件名
        self.file_name = file_name
        self.data_only = data_only
        self.workbook = None  #工作薄对象
        self.worksheet = None  #表对象sheet

    def __enter__(self):
        path = get_file_path(self.file_name, Absolute=True)
        if os.path.exists(path):
            #文件存在就加载，加载失败报错
            try:
                self.workbook = openpyxl.load_workbook(get_file_path(self.file_name), data_only=self.data_only)
            except:
                print('加载excel文件失败！')
        else:
            print('加载excel文件不存在！自动创建文件！')
            self.workbook = openpyxl.Workbook()
        return self

    def openWorkSheet(self, strSheetName) -> Worksheet:  #表示此函数 的返回值 ，是这样的类型，函数 注解
        '''
        打开工作表
        strSheetName：sheet名称
        return Worksheet对象'''
        if strSheetName in self.workbook.sheetnames:
            self.worksheet = self.workbook[strSheetName]
        else:
            print('表单名称在当前excel文件中不存在！')

        return self.worksheet

    def getDataByCell(self, nRow, nColunm):
        '''
        读取一个单元格的数据功能
        nRow ：行号 1，2，3……
        nColunm： 列号 1,2,3
        return 指定单元格数值'''
        #判断行号，列号有效
        if self.isCheckNumValid(nRow, self.worksheet.max_row) is True and self.isCheckNumValid(nColunm, self.worksheet.max_column) is True:
            return self.worksheet.cell(nRow, nColunm).value

    # def putDataByCell(self, nRow, nColumn, value):
    #     """
    #     写入一个单元格数据功能
    #     :param nRow: 行号1,2,...
    #     :param nColumn: 列号1,2,...
    #     :param value: 写入指定单元格的数值
    #     """
    #     self.worksheet.cell(nRow, nColumn).value = value

    # def saveWorkBookData(self, strSaveFilePath):
    #     """
    #     保存工作簿数据功能
    #     :param strSaveFilePath: 保存或另存工作簿的路径
    #     """
    #     try:
    #         self.workbook.save(strSaveFilePath)
    #     except PermissionError:
    #         print("要操作的文件，没有写入权限，请检查权限！")
    #         raise
    #     except FileNotFoundError:
    #         print("文件路径不存在，请确保路径正确！")
    #         raise
    #     except:
    #         print("保存写入的数据失败！请检查异常!")
    #         raise

    def __exit__(self, exc_type, exc_val, exc_tb):
        '''
        关闭工作薄'''
        self.workbook.close()

    @staticmethod
    def isCheckNumValid(cur_num, max_num):
        '''
        检测数据有效
        cur_num ：当前指定的行号或列号 1，2，3……
        max_num ：当前工作表最大行号或列号 1,2,3
        return True表示数据有效，否则False
        '''
        #类型检测
        if type(cur_num) is not int and type(cur_num) is not str:
            print("cur_num 数据类型错误！请使用int或str!")
            return False
        #数字检测，str能否转为int
        if type(cur_num) is str:
            try:
                cur_num = int(cur_num)
            except:
                print("cur_num 参数非法！请使用整数数字!")
                return False
        #数字范围校验
        if cur_num in range(1, max_num + 1):
            return True
        else:
            print("行号或者列号，超出了目前最大行号，或者最大列号！！")
            return False

    @staticmethod
    def justOpen(strFileName):
        """
		模拟手工打开excel表
		:param strFileName: 打开的excel文件名（后缀.xlsx格式）
		"""
        try:
            xlApp = DispatchEx("Excel.Application")
            xlApp.Visible = False
            xlBook = xlApp.Workbooks.Open(os.path.join(os.getcwd(), strFileName))
            xlBook.Save()
            xlBook.Close()
        except:
            print("请手工打开 %s 后，随便修改一个空值并保存" % strFileName)


"""
========================================
主函数功能测试
========================================
"""
if __name__ == '__main__':
    # 对自己定义的功能类进行测试
    # 正常功能测试
    # myExcel = MyPyExcel("demo.xlsx")  # 加载文件
    # myExcel.openWorkSheet("test")  # 选择工作表
    # # myExcel.putDataByCell(1, 1, 100)  # 写入一个单元格数据
    # # myExcel.putDataByCell(2, 1, 400)  # 写入一个单元格数据
    # # myExcel.putDataByCell(3, 1, "=SUM(A1:A2)")  # 写入一个单元格公式
    # # myExcel.saveWorkBookData("test.xlsx")  # 保存数据
    # print(myExcel.getDataByCell(1, 3))
    # myExcel.closeWorkBook()  # 关闭工作簿
    # myExcel.justOpen("test.xlsx")  # 模拟手工打开excel表
    # """读取单元格的数值。data_only=True"""
    # myExcel2 = MyPyExcel("demo.xlsx")  # 加载文件
    # myExcel2.openWorkSheet("Sheet")  # 选择工作表
    # print(myExcel2.getDataByCell(3, 1))  # 读取某一个单元格数据
    # myExcel2.closeWorkBook()  # 关闭工作簿
    # """读取单元格的公式。data_only=False"""
    # myExcel3 = MyPyExcel("demo.xlsx", False)  # 加载文件
    # myExcel3.openWorkSheet("Sheet")  # 选择工作表
    # print(myExcel3.getDataByCell(3, 1))  # 读取某一个单元格公式
    # myExcel3.closeWorkBook()  # 关闭工作簿

    #增加上下文处理，可以直接with调用
    with MyPyExcel("demo.xlsx") as f:
        # f.openWorkSheet("test")
        # print(f.getDataByCell(1, 3))
        for sheet in f.workbook:  #使用for循环遍历所有的工作表：
            print('sheet', f.workbook.index(sheet), ':', sheet.title)
        for row in f.openWorkSheet("test"):
            for cell in row:
                print(cell.row, cell.column, ':', cell.value)
        print(list(f.openWorkSheet('test').rows))
